#include "SystemCatalog.h"
#include <iostream>
#include <cstring>

namespace MiniDB {

SystemCatalog::SystemCatalog(std::shared_ptr<StorageManager> storage_manager)
    : storage_manager_(storage_manager), catalog_page_id_(-1), is_dirty_(false) {
    std::cout << "SystemCatalog initialized" << std::endl;
    loadCatalog(); // 尝试加载现有目录
}

SystemCatalog::~SystemCatalog() {
    if (is_dirty_) {
        saveCatalog();
    }
    std::cout << "SystemCatalog destroyed" << std::endl;
}

bool SystemCatalog::createTable(const std::string& table_name, const std::vector<ColumnInfo>& columns) {
    if (tableExists(table_name)) {
        std::cerr << "Error: Table '" << table_name << "' already exists" << std::endl;
        return false;
    }

    // 在存储管理器中创建实际的表
    if (!storage_manager_->createTable(table_name)) {
        return false;
    }

    // 创建目录条目
    CatalogEntry entry(table_name);
    entry.columns = columns;
    entry.root_page_id = 1; // 简化实现

    catalog_entries_[table_name] = entry;
    is_dirty_ = true;

    std::cout << "Table '" << table_name << "' registered in system catalog" << std::endl;
    return true;
}

bool SystemCatalog::dropTable(const std::string& table_name) {
    auto it = catalog_entries_.find(table_name);
    if (it == catalog_entries_.end()) {
        std::cerr << "Error: Table '" << table_name << "' not found in catalog" << std::endl;
        return false;
    }

    // 从存储管理器中删除表
    if (!storage_manager_->dropTable(table_name)) {
        return false;
    }

    catalog_entries_.erase(it);
    is_dirty_ = true;

    std::cout << "Table '" << table_name << "' removed from system catalog" << std::endl;
    return true;
}

bool SystemCatalog::tableExists(const std::string& table_name) const {
    return catalog_entries_.find(table_name) != catalog_entries_.end();
}

std::vector<std::string> SystemCatalog::getTableNames() const {
    std::vector<std::string> names;
    names.reserve(catalog_entries_.size());
    for (const auto& pair : catalog_entries_) {
        names.push_back(pair.first);
    }
    return names;
}

const CatalogEntry* SystemCatalog::getTableEntry(const std::string& table_name) const {
    auto it = catalog_entries_.find(table_name);
    if (it != catalog_entries_.end()) {
        return &it->second;
    }
    return nullptr;
}

bool SystemCatalog::updateTableStats(const std::string& table_name, size_t record_count, size_t total_size) {
    auto it = catalog_entries_.find(table_name);
    if (it == catalog_entries_.end()) {
        return false;
    }

    it->second.record_count = record_count;
    it->second.total_size = total_size;
    is_dirty_ = true;
    return true;
}

bool SystemCatalog::saveCatalog() {
    if (!is_dirty_) {
        return true; // 没有变化，无需保存
    }

    std::vector<char> buffer;
    if (!serializeCatalog(buffer)) {
        std::cerr << "Error: Failed to serialize catalog" << std::endl;
        return false;
    }

    // 分配或获取目录页面
    if (catalog_page_id_ == -1) {
        if (!allocateCatalogPage()) {
            return false;
        }
    }

    // 写入到存储系统
    std::cout << "SystemCatalog::saveCatalog: Writing " << buffer.size() << " bytes to page " << catalog_page_id_ << std::endl;
    if (!storage_manager_->writePage(catalog_page_id_, buffer.data(), buffer.size())) {
        std::cerr << "Error: Failed to write catalog to disk" << std::endl;
        return false;
    }

    is_dirty_ = false;
    std::cout << "System catalog saved to disk (page " << catalog_page_id_ << ", " << buffer.size() << " bytes)" << std::endl;
    return true;
}

bool SystemCatalog::loadCatalog() {
    if (catalog_page_id_ == -1) {
        // 尝试查找现有的目录页面
        // 简化实现：假设目录存储在页面0
        catalog_page_id_ = 0;
    }

    std::vector<char> buffer(PAGE_SIZE);
    if (!storage_manager_->readPage(catalog_page_id_, buffer.data(), buffer.size())) {
        std::cout << "No existing catalog found, starting with empty catalog" << std::endl;
        return true; // 没有现有目录，从空目录开始
    }

    // 检查buffer是否有有效数据（至少包含entry_count）
    if (buffer.empty() || buffer.size() < sizeof(size_t)) {
        std::cout << "Catalog page is empty or too small, starting with empty catalog" << std::endl;
        return true;
    }

    if (!deserializeCatalog(buffer)) {
        std::cerr << "Error: Failed to deserialize catalog, starting with empty catalog" << std::endl;
        // 即使反序列化失败，也不要返回false，而是清空目录从头开始
        catalog_entries_.clear();
        return true;
    }

    std::cout << "System catalog loaded from disk (" << catalog_entries_.size() << " tables)" << std::endl;

    // 恢复StorageManager中的表信息
    restoreTablesInStorageManager();

    return true;
}

void SystemCatalog::printCatalog() const {
    std::cout << "\n=== System Catalog ===" << std::endl;
    if (catalog_entries_.empty()) {
        std::cout << "Catalog is empty" << std::endl;
        return;
    }

    for (const auto& pair : catalog_entries_) {
        const CatalogEntry& entry = pair.second;
        std::cout << "📋 Table: " << entry.table_name << std::endl;
        std::cout << "   Root Page: " << entry.root_page_id << std::endl;
        std::cout << "   Records: " << entry.record_count << std::endl;
        std::cout << "   Total Size: " << entry.total_size << " bytes" << std::endl;
        std::cout << "   Columns:" << std::endl;

        for (const auto& col : entry.columns) {
            std::string type_str = col.type; // 直接使用字符串类型
            
            // 格式化输出（可选）
            if (col.type == "INT") type_str = "INT";
            else if (col.type == "VARCHAR") type_str = "VARCHAR";
            else if (col.type == "FLOAT") type_str = "FLOAT";
            else if (col.type == "BOOLEAN") type_str = "BOOLEAN";
            else if (col.type == "DATE") type_str = "DATE";
            else if (col.type == "TEXT") type_str = "TEXT";
            
            std::cout << "     • " << col.name << " (" << type_str << ")";
            if (col.is_primary_key) std::cout << " [PK]";
            if (!col.nullable) std::cout << " [NOT NULL]";
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
}

bool SystemCatalog::serializeCatalog(std::vector<char>& buffer) const {
    try {
        buffer.clear();

        // 写入条目数量
        size_t entry_count = catalog_entries_.size();
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&entry_count),
                     reinterpret_cast<const char*>(&entry_count) + sizeof(entry_count));

        // 序列化每个条目
        for (const auto& pair : catalog_entries_) {
            if (!serializeEntry(pair.second, buffer)) {
                return false;
            }
        }

        return true;
    } catch (const std::exception& e) {
        std::cerr << "Serialization error: " << e.what() << std::endl;
        return false;
    }
}

bool SystemCatalog::deserializeCatalog(const std::vector<char>& buffer) {
    try {
        // 边界检查 - 确保buffer至少有entry_count的大小
        if (buffer.size() < sizeof(size_t)) {
            std::cerr << "Error: Buffer too small for catalog header" << std::endl;
            return false;
        }

        size_t offset = 0;

        // 读取条目数量
        size_t entry_count;
        std::memcpy(&entry_count, buffer.data() + offset, sizeof(entry_count));
        offset += sizeof(entry_count);

        // 反序列化每个条目
        for (size_t i = 0; i < entry_count; ++i) {
            CatalogEntry entry;
            if (!deserializeEntry(buffer, entry, offset)) {
                std::cerr << "Error: Failed to deserialize catalog entry " << i << std::endl;
                return false;
            }
            catalog_entries_[entry.table_name] = entry;
        }

        return true;
    } catch (const std::exception& e) {
        std::cerr << "Deserialization error: " << e.what() << std::endl;
        return false;
    }
}

bool SystemCatalog::serializeEntry(const CatalogEntry& entry, std::vector<char>& buffer) const {
    try {
        // 表名
        size_t name_size = entry.table_name.size();
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&name_size),
                     reinterpret_cast<const char*>(&name_size) + sizeof(name_size));
        buffer.insert(buffer.end(), entry.table_name.begin(), entry.table_name.end());

        // 根页面ID
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&entry.root_page_id),
                     reinterpret_cast<const char*>(&entry.root_page_id) + sizeof(entry.root_page_id));

        // 记录数
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&entry.record_count),
                     reinterpret_cast<const char*>(&entry.record_count) + sizeof(entry.record_count));

        // 总大小
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&entry.total_size),
                     reinterpret_cast<const char*>(&entry.total_size) + sizeof(entry.total_size));

        // 列数量
        size_t col_count = entry.columns.size();
        buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col_count),
                     reinterpret_cast<const char*>(&col_count) + sizeof(col_count));

        // 序列化每个列
        for (const auto& col : entry.columns) {
            // 列名
            size_t col_name_size = col.name.size();
            buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col_name_size),
                         reinterpret_cast<const char*>(&col_name_size) + sizeof(col_name_size));
            buffer.insert(buffer.end(), col.name.begin(), col.name.end());

            // 数据类型
            buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col.type),
                         reinterpret_cast<const char*>(&col.type) + sizeof(col.type));

            // 大小
            buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col.size),
                         reinterpret_cast<const char*>(&col.size) + sizeof(col.size));

            // 可空性
            buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col.nullable),
                         reinterpret_cast<const char*>(&col.nullable) + sizeof(col.nullable));

            // 主键
            buffer.insert(buffer.end(), reinterpret_cast<const char*>(&col.is_primary_key),
                         reinterpret_cast<const char*>(&col.is_primary_key) + sizeof(col.is_primary_key));
        }

        return true;
    } catch (const std::exception& e) {
        std::cerr << "Entry serialization error: " << e.what() << std::endl;
        return false;
    }
}

bool SystemCatalog::deserializeEntry(const std::vector<char>& buffer, CatalogEntry& entry, size_t& offset) const {
    try {
        // 边界检查
        if (offset + sizeof(size_t) > buffer.size()) {
            std::cerr << "Error: Buffer too small for name_size" << std::endl;
            return false;
        }

        // 表名
        size_t name_size;
        std::memcpy(&name_size, buffer.data() + offset, sizeof(name_size));
        offset += sizeof(name_size);

        if (offset + name_size > buffer.size()) {
            std::cerr << "Error: Buffer too small for table name" << std::endl;
            return false;
        }

        entry.table_name.assign(buffer.begin() + offset, buffer.begin() + offset + name_size);
        offset += name_size;

        // 边界检查 - 根页面ID
        if (offset + sizeof(entry.root_page_id) > buffer.size()) {
            std::cerr << "Error: Buffer too small for root_page_id" << std::endl;
            return false;
        }

        // 根页面ID
        std::memcpy(&entry.root_page_id, buffer.data() + offset, sizeof(entry.root_page_id));
        offset += sizeof(entry.root_page_id);

        // 边界检查 - 记录数
        if (offset + sizeof(entry.record_count) > buffer.size()) {
            std::cerr << "Error: Buffer too small for record_count" << std::endl;
            return false;
        }

        // 记录数
        std::memcpy(&entry.record_count, buffer.data() + offset, sizeof(entry.record_count));
        offset += sizeof(entry.record_count);

        // 边界检查 - 总大小
        if (offset + sizeof(entry.total_size) > buffer.size()) {
            std::cerr << "Error: Buffer too small for total_size" << std::endl;
            return false;
        }

        // 总大小
        std::memcpy(&entry.total_size, buffer.data() + offset, sizeof(entry.total_size));
        offset += sizeof(entry.total_size);

        // 边界检查 - 列数量
        if (offset + sizeof(size_t) > buffer.size()) {
            std::cerr << "Error: Buffer too small for column count" << std::endl;
            return false;
        }

        // 列数量
        size_t col_count;
        std::memcpy(&col_count, buffer.data() + offset, sizeof(col_count));
        offset += sizeof(col_count);

        // 反序列化每个列
        for (size_t i = 0; i < col_count; ++i) {
            ColumnInfo col;

            // 边界检查 - 列名大小
            if (offset + sizeof(size_t) > buffer.size()) {
                std::cerr << "Error: Buffer too small for column name size" << std::endl;
                return false;
            }

            // 列名
            size_t col_name_size;
            std::memcpy(&col_name_size, buffer.data() + offset, sizeof(col_name_size));
            offset += sizeof(col_name_size);

            // 边界检查 - 列名
            if (offset + col_name_size > buffer.size()) {
                std::cerr << "Error: Buffer too small for column name" << std::endl;
                return false;
            }

            col.name.assign(buffer.begin() + offset, buffer.begin() + offset + col_name_size);
            offset += col_name_size;

            // 边界检查 - 数据类型字符串大小
            if (offset + sizeof(size_t) > buffer.size()) {
                std::cerr << "Error: Buffer too small for column type size" << std::endl;
                return false;
            }

            // 数据类型（字符串）
            size_t col_type_size;
            std::memcpy(&col_type_size, buffer.data() + offset, sizeof(col_type_size));
            offset += sizeof(col_type_size);

            // 边界检查 - 数据类型字符串
            if (offset + col_type_size > buffer.size()) {
                std::cerr << "Error: Buffer too small for column type" << std::endl;
                return false;
            }

            col.type.assign(buffer.begin() + offset, buffer.begin() + offset + col_type_size);
            offset += col_type_size;

            // 边界检查 - 大小
            if (offset + sizeof(col.size) > buffer.size()) {
                std::cerr << "Error: Buffer too small for column size" << std::endl;
                return false;
            }

            // 大小
            std::memcpy(&col.size, buffer.data() + offset, sizeof(col.size));
            offset += sizeof(col.size);

            // 边界检查 - 可空性
            if (offset + sizeof(col.nullable) > buffer.size()) {
                std::cerr << "Error: Buffer too small for nullable flag" << std::endl;
                return false;
            }

            // 可空性
            std::memcpy(&col.nullable, buffer.data() + offset, sizeof(col.nullable));
            offset += sizeof(col.nullable);

            // 边界检查 - 主键
            if (offset + sizeof(col.is_primary_key) > buffer.size()) {
                std::cerr << "Error: Buffer too small for primary key flag" << std::endl;
                return false;
            }

            std::memcpy(&col.is_primary_key, buffer.data() + offset, sizeof(col.is_primary_key));
            offset += sizeof(col.is_primary_key);

            entry.columns.push_back(col);
        }

        return true;
    } catch (const std::exception& e) {
        std::cerr << "Entry deserialization error: " << e.what() << std::endl;
        return false;
    }
}

bool SystemCatalog::allocateCatalogPage() {
    // 简化实现：使用固定页面ID
    catalog_page_id_ = 0;
    return true;
}

void SystemCatalog::restoreTablesInStorageManager() {
    if (!storage_manager_) {
        std::cerr << "Error: StorageManager not available for table restoration" << std::endl;
        return;
    }

    std::cout << "Restoring " << catalog_entries_.size() << " tables in StorageManager..." << std::endl;

    for (const auto& pair : catalog_entries_) {
        const std::string& table_name = pair.first;
        const CatalogEntry& entry = pair.second;

        // 在StorageManager中重新创建表结构（不分配新页面，因为页面ID已知）
        if (!storage_manager_->tableExists(table_name)) {
            // 手动创建表元数据，避免重新分配页面
            storage_manager_->restoreTableMetadata(table_name, entry.root_page_id, entry.record_count, entry.total_size);
            std::cout << "   Restored table '" << table_name << "' with page " << entry.root_page_id << std::endl;
        }
    }

    std::cout << "Table restoration completed" << std::endl;
}

} // namespace MiniDB
